using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Diagnostics;
using log4net.Core;
using System.Configuration;

namespace UsingLib
{
    /// <summary>
    /// the method should nbe prefixed with
    ///  <System.Runtime.CompilerServices.MethodImpl( _
    ///System.Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
    /// see http://www.lhotka.net/Article.aspx?id=0708c745-f009-4d09-9f91-6a349b5b0317
    /// and http://blogs.msdn.com/jmstall/archive/2005/03/20/399287.aspx
    /// for a quick start , put the following in the app.config file 
    /// <?xml version="1.0" encoding="utf-8" ?>
    ///<configuration>
    ///    <appSettings>
    ///        <add key="usingLog4Net_Logger" value="RollingLogFileAppender"/>
    ///    </appSettings>
    ///    <configSections>
    ///        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    ///    </configSections>
    ///    <log4net>
    ///        <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    ///            <File value="Logs\\Log4Net.log"/>
    ///            <AppendToFile value="true"/>
    ///            <rollingStyle value="Composite"/>
    ///            <maximumFileSize value="10MB"/>
    ///            <maxSizeRollBackups value="10"/>
    ///            <datePattern value="yyyyMMdd"/>
    ///            <!--
    ///      <filter type="log4net.Filter.LevelRangeFilter">
    ///        <acceptOnMatch value="true" />
    ///        <levelMin value="INFO" />
    ///        <levelMax value="FATAL" />
    ///      </filter>
    ///      <layout type="log4net.Layout.PatternLayout">
    ///        <conversionPattern
    ///        value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
    ///      </layout>
    ///      -->
    ///            <layout type="log4net.Layout.PatternLayout">
    ///                <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
    ///            </layout>
    ///        </appender>
    ///        <root>
    ///            <level value="Info"/>
    ///            <appender-ref ref="RollingLogFileAppender"/>
    ///        </root>
    ///    </log4net>
    ///</configuration>
    /// </summary>
    public class usingLog4Net :IDisposable
    {
        /// <summary>
        /// create the unique logger 
        /// </summary>
        static usingLog4Net()
        {
            log4net.Config.XmlConfigurator.Configure();
            AppSettingsSection a = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings;
            string logfile = a.Settings["usingLog4Net_Logger"].Value;
            logger = log4net.LogManager.GetLogger(logfile);
            
        }
        /// <summary>
        /// logger - initialized in <see cref="usingLog4Net.usingLog4Net"/>
        /// </summary>
        private  static readonly log4net.ILog logger = null;
        
        /// <summary>
        /// level of logging
        /// </summary>
        private Level m_level;

        /// <summary>
        /// method that call the logger
        /// </summary>
        private MethodBase m_Method;
        
        /// <summary>
        /// constructor 
        /// </summary>
        /// <param name="theLevel">level to log -you can save this in config file</param>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public usingLog4Net(Level theLevel)
        {
            m_level = theLevel;            
            LogMethod();
        }
        /// <summary>
        /// log the currrent method
        /// </summary>
        [MethodImpl(MethodImplOptions.NoInlining)]
        private void LogMethod()
        {
            
            StackTrace st = new StackTrace(true);
            StackFrame[] sf = st.GetFrames();
            StackFrame sfMethod = sf[ 3]; //0 - LogMethod, 1 : constructor, 2:using             
            m_Method = sfMethod.GetMethod();            
            LogText("Enter method " + m_Method.Name);
                
            
        }
        /// <summary>
        /// can be used for your own purposes to log something
        /// </summary>
        /// <param name="Text"></param>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public void LogText(string Text)
        {
            if (m_level== Level.Debug && logger.IsDebugEnabled )
            {
                logger.Debug(Text);
                return;
            }

            if (m_level == Level.Info && logger.IsInfoEnabled)
            {
                logger.Info(Text);
                return;
            }
            if (m_level == Level.Warn && logger.IsWarnEnabled )
            {
                logger.Warn(Text);
                return;
            }

            if (m_level == Level.Error && logger.IsErrorEnabled)
            {
                logger.Error(Text);
                return;
            }

            if (m_level == Level.Fatal && logger.IsFatalEnabled)
            {
                logger.Fatal(Text);
                return;
            }
        }

        #region IDisposable Members
        /// <summary>
        /// used with using 
        /// </summary>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public void Dispose()
        {
            
            LogText("exit method " + m_Method.Name);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
